package com.lonely.order.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.SerializeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.lonely.api.mes.model.dto.DomesticBulkGoodsPlaceOrderDTO;
import com.lonely.api.mes.service.ISynchronizedMesService;
import com.lonely.common.constant.OrderConstants;
import com.lonely.common.core.domain.BaseEntity;
import com.lonely.common.core.domain.Select;
import com.lonely.common.core.domain.StatusInfo;
import com.lonely.common.core.domain.auth.LoginUser;
import com.lonely.common.core.page.Condition;
import com.lonely.common.core.redis.RedisCache;
import com.lonely.common.enums.CommonStatus;
import com.lonely.common.exception.BusinessException;
import com.lonely.common.threadlocals.LoginUserThreadLocal;
import com.lonely.common.utils.JsonUtil;
import com.lonely.common.utils.SecurityUtils;
import com.lonely.common.utils.enums.Enum2SelectsUtil;
import com.lonely.deliver.domain.dto.SyncProgressDTO;
import com.lonely.framework.websocket.WebSocketUtil;
import com.lonely.goods.domain.dto.goods.*;
import com.lonely.goods.domain.entity.SysGoods;
import com.lonely.goods.domain.entity.SysGoodsPartMaterial;
import com.lonely.goods.domain.entity.SysGoodsSecondProcess;
import com.lonely.goods.domain.vo.goods.CopyBomQueryVO;
import com.lonely.goods.domain.vo.goods.GoodsQuotationSheetTotalCastVO;
import com.lonely.goods.domain.vo.goods.GoodsQuotationSheetVO;
import com.lonely.goods.enums.GoodsEnum;
import com.lonely.goods.service.IGoodsPartMaterialService;
import com.lonely.goods.service.IGoodsPartService;
import com.lonely.goods.service.IGoodsSecondProcessService;
import com.lonely.goods.service.IGoodsService;
import com.lonely.order.domain.dto.api.NumberInfo;
import com.lonely.order.domain.dto.api.QueryProduceOrderInfoByIdReqDTO;
import com.lonely.order.domain.dto.api.QueryProduceOrderInfoByIdResDTO;
import com.lonely.order.domain.dto.api.SecondProcessInfo;
import com.lonely.order.domain.dto.order.*;
import com.lonely.order.domain.entity.SysOrder;
import com.lonely.order.domain.entity.SysOrderPart;
import com.lonely.order.domain.entity.SysOrderPartMaterial;
import com.lonely.order.domain.entity.SysSheinOpenApiSecret;
import com.lonely.order.domain.vo.order.*;
import com.lonely.order.domain.vo.split.GetSplitFactoryNameVO;
import com.lonely.order.enums.OrderEnum;
import com.lonely.order.mapper.SysOrderMapper;
import com.lonely.order.service.*;
import com.lonely.order.support.detail.GetOrderDetailFactory;
import com.lonely.order.support.print.skcsticker.PrintSkcStickerPdfFactory;
import com.lonely.order.support.synchronizer.service.StartSynchronizerOrderService;
import com.lonely.order.threadlocals.OrderSynchronizedThreadLocal;
import com.lonely.purchase.domain.entity.SysMaterialPurchase;
import com.lonely.purchase.enums.MaterialPurchaseEnum;
import com.lonely.purchase.service.IMaterialPurchaseService;
import com.lonely.system.domain.entity.SysCustomer;
import com.lonely.system.domain.entity.SysFactory;
import com.lonely.system.service.ISysCustomerService;
import com.lonely.system.service.ISysFactoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 *
 * @author fzzf
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<SysOrderMapper, SysOrder> implements IOrderService {

    @Autowired
    private IOrderLogService orderLogService;

    @Autowired
    private ISysFactoryService sysFactoryService;

    @Autowired
    private ISysSheinOpenApiSecretService sheinOpenApiSecretService;

    @Autowired
    private IOrderTagService orderTagService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IMesApiService mesApiService;

    @Autowired
    private IOrderSplitService orderSplitService;

    @Autowired
    private IGoodsPartService goodsPartService;

    @Autowired
    private IMaterialPurchaseService materialPurchaseService;

    @Autowired
    private IGoodsSecondProcessService goodsSecondProcessService;

    @Autowired
    private IOrderPartService orderPartService;

    @Autowired
    private IGoodsPartMaterialService goodsPartMaterialService;

    @Autowired
    private IOrderPartMaterialService orderPartMaterialService;

    @Autowired
    private IOrderProcessService orderProcessService;

    @Autowired
    private StartSynchronizerOrderService startSynchronizerOrderService;

    @Autowired
    private ISynchronizedMesService synchronizedMesService;

    @Autowired
    private ISysCustomerService customerService;

    @Autowired
    private IGoodsService goodsService;

    /**
     * 同步订单数据(最近一个月的)
     */
    @Override
//    @Transactional(rollbackFor = Exception.class)
    public void synchronizerLastMonthOrder() {
        // 获取当前用户对应的openapi 密钥信息
        List<SysSheinOpenApiSecret> openApiSecrets = this.sheinOpenApiSecretService.queryApiSecretListByLoginUser();
        if (CollUtil.isEmpty(openApiSecrets)) {
            return;
        }

//        ExecutorService executor = Executors.newFixedThreadPool(10); // 线程池
//        List<CompletableFuture<Void>> futures = new ArrayList<>();

        //获取当前日期的进一个月日期
//        DateTime lastMonthDate = DateUtil.lastMonth();
//        DateTime lastMonthDate = DateUtil.yesterday();

        // TODO 测试，获取三天前的日期
        DateTime lastMonthDate = DateUtil.offsetDay(new Date(), -3);

        // 创建日期范围（包含开始和结束日期）
        long betweenDay = DateUtil.betweenDay(lastMonthDate, new Date(), true);
//        for (int i = 0; i < betweenDay; i++) {
//            DateTime currentDate = DateUtil.offsetDay(lastMonthDate, i);
//            String currentDateStr = DateUtil.formatDate(currentDate);
//            log.debug("开始同步日期为：{} 的订单数据", currentDateStr);
//            try {
//                this.synchronizerOrderByDate(currentDate);
//                log.debug("同步日期为：{} 的订单数据完成", currentDateStr);
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
//        }

//        for (int i = 0; i <= betweenDay; i++) {
//            DateTime currentDate = DateUtil.offsetDay(lastMonthDate, i);
////            for (SysSheinOpenApiSecret openApiSecret : openApiSecrets) {
//            SysSheinOpenApiSecret openApiSecret = openApiSecrets.get(0);
//            OrderSynchronizedThread synchronizedThread = new OrderSynchronizedThread(currentDate, SecurityUtils.getUserId(), openApiSecret);
//            futures.add(CompletableFuture.runAsync(synchronizedThread, executor));
////            }
//        }
//
//        CompletableFuture<Void> completableFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
//                .thenRun(() -> log.debug("最近一个月订单已同步完毕~~"))
//                .exceptionally(ex -> {
//                    log.error("订单同步执行异常：{}", ExceptionUtils.getStackTrace(ex));
//                    return null;
//                });
//
//        // 等待任务执行完毕
//        completableFuture.join();
//        executor.shutdown(); // 关闭线程池

        Boolean isWebsocket = OrderSynchronizedThreadLocal.getIsWebsocket();
        String destination = OrderSynchronizedThreadLocal.getDestination();
        Long createBy = OrderSynchronizedThreadLocal.getCreateBy();
        LoginUser loginUser = LoginUserThreadLocal.getLoginUser();

        // 使用同步处理
        try {
            // 原子计数器
            AtomicInteger completedTasks = new AtomicInteger(0);
            int totalTasks = Convert.toInt((betweenDay + 1) * openApiSecrets.size());

            if (isWebsocket) {
                WebSocketUtil.sendToUser(SecurityUtils.getUsername(), destination, SyncProgressDTO.buildProgressResult(0, "开始同步订单数据"));
            }

            CompletableFuture.runAsync(() -> {
                        for (int i = 0; i <= betweenDay; i++) {
                            DateTime currentDate = DateUtil.offsetDay(lastMonthDate, i);
                            for (SysSheinOpenApiSecret openApiSecret : openApiSecrets) {
                                LoginUserThreadLocal.setLoginUser(loginUser);
                                OrderSynchronizedThreadLocal.setIsWebsocket(isWebsocket);
                                OrderSynchronizedThreadLocal.setDestination(destination);
                                OrderSynchronizedThreadLocal.setCreateBy(createBy);
                                OrderSynchronizedThreadLocal.setTotalSize(totalTasks);
                                String currentDateStr = DateUtil.formatDate(currentDate);
                                log.debug("开始同步工厂id:{},日期为：{} 的订单数据", openApiSecret.getFactoryId(), currentDateStr);

                                try {
                                    this.startSynchronizerOrderService.synchronizerOrderByDate(openApiSecret, currentDate);
                                    log.debug("同步工厂id:{},日期为：{} 的订单数据完成", openApiSecret.getFactoryId(), currentDateStr);
                                } catch (Exception e) {
                                    log.error("同步工厂id:{},日期为：{} 的订单数据失败，异常原因：{}", openApiSecret.getFactoryId(), currentDateStr, ExceptionUtils.getStackTrace(e));
                                } finally {
                                    // 任务完成，计数+1
                                    int completed = completedTasks.incrementAndGet();
                                    OrderSynchronizedThreadLocal.setCurrentSize(completed);
                                    this.sendHasProgressMessage("同步中...");

                                    OrderSynchronizedThreadLocal.clear();
                                }

                            }
                        }
                    }).thenRun(() -> {
                        log.debug("最近一个月订单已同步完毕~~");
                        if (isWebsocket) {
                            WebSocketUtil.sendToUser(SecurityUtils.getUsername(), destination, SyncProgressDTO.buildCompletedResult("同步完成"));
                        }
                    })
                    .exceptionally(ex -> {
                        log.error("订单同步执行异常：{}", ExceptionUtils.getStackTrace(ex));
                        return null;
                    });

        } finally {
            OrderSynchronizedThreadLocal.clear();
        }

    }


    /**
     * 发送同步进行中(有进度的)消息
     */
    private void sendHasProgressMessage(String message) {
        if (OrderSynchronizedThreadLocal.getIsWebsocket()) {
            WebSocketUtil.sendToUser(SecurityUtils.getUsername(), OrderSynchronizedThreadLocal.getDestination(), SyncProgressDTO.buildProgressResult(OrderSynchronizedThreadLocal.getProgress(), message));
        }
    }

    /**
     * 同步今天的订单数据
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void synchronizerTodayOrder() {
        // 查找全部的对接的api的密钥信息
        List<SysSheinOpenApiSecret> sheinOpenApiSecrets = this.sheinOpenApiSecretService.queryAll();
        if (CollUtil.isEmpty(sheinOpenApiSecrets)) {
            return;
        }
        for (SysSheinOpenApiSecret openApiSecret : sheinOpenApiSecrets) {
//            OrderSynchronizerHelp.synchronizerOrderByDate(openApiSecret, new Date());
            this.startSynchronizerOrderService.synchronizerOrderByDate(openApiSecret, new Date());
        }
    }


    /**
     * 分页获取订单列表
     *
     * @param queryDto
     * @return
     */
    @Override
    public Page<QueryProduceOrderPageVO> produceOrderPage(QueryProduceOrderPageDTO queryDto) {

        // 获取当前登陆用户拥有的工厂权限
        Set<String> factoryDataPermissions = this.getFactoryDataPermissions();
        if (CollUtil.isEmpty(factoryDataPermissions)) {
            return new Page<>(queryDto.getCurrent(), queryDto.getSize());
        }

        // 预处理数据
        this.orderPageQueryParamPreHandle(queryDto);

        // 执行查询
        Page<QueryProduceOrderPageDTO> page = Condition.page(queryDto);
        Page<QueryProduceOrderPageVO> resultPage = super.getBaseMapper().orderPage(page, queryDto, new ArrayList<>(factoryDataPermissions));

        if (CollUtil.isNotEmpty(resultPage.getRecords())) {
            List<Long> orderIds = resultPage.getRecords().stream().map(QueryProduceOrderPageVO::getId).distinct().collect(Collectors.toList());
            Map<Long, List<OrderTagVO>> orderTagMap = this.orderTagService.queryOrderTagsByOrderIds(orderIds).stream()
                    .collect(Collectors.groupingBy(OrderTagVO::getOrderId));
            Set<Long> hasOrderNoteLogSet = this.orderLogService.hasOrderNoteLogByOrderIds(orderIds);
            Map<Long, GetSplitFactoryNameVO> splitOrderFactoryNameMap = this.orderSplitService.getSplitFactoryNameByOrderIds(orderIds);

            // 判断是否拥有展示金额的权限
            boolean hasPermission = StpUtil.hasPermission(OrderConstants.ORDER_FOLLOW_LIST_SHOW_ORDER_PRICE_PERM);

            resultPage.setRecords(resultPage.getRecords().stream().peek(order -> {

                // 设置分单工厂名称
                if (splitOrderFactoryNameMap.containsKey(order.getId())) {
                    order.setWorkshopSplitFactoryName(splitOrderFactoryNameMap.get(order.getId()).getWorkshopFactoryName());
                    order.setWorkshopSplitProductionLineName(splitOrderFactoryNameMap.get(order.getId()).getWorkshopProductionLineName());
                    order.setTailSplitFactoryName(splitOrderFactoryNameMap.get(order.getId()).getTailFactoryName());
                    order.setTailSplitProductionLineName(splitOrderFactoryNameMap.get(order.getId()).getTailProductionLineName());
                }

                // 是否隐藏订单金额
                if (!hasPermission) {
                    order.setOrderPrice("***");
                }

                // 设置标签
                List<QueryProduceOrderPageVO.Tag> tags = new ArrayList<>();

                // 订单标签
                if (CollUtil.isNotEmpty(orderTagMap.get(order.getId()))) {
                    orderTagMap.get(order.getId()).forEach(orderTag -> {
                        tags.add(new QueryProduceOrderPageVO.Tag()
                                .setTagId(orderTag.getTagId())
                                .setTagName(orderTag.getTagName())
                                .setColor(orderTag.getTagColorType())
                                .setIsOrderTag(true));
                    });
                }

                // 基础标签
                if (Objects.equals(OrderEnum.IsFirstOrder.FIRST_ORDER.getType(), order.getIsFirst())) {
                    tags.add(new QueryProduceOrderPageVO.Tag().setTagName("首").setColor("info"));
                }
                if (Objects.equals(OrderEnum.IsFirstOrder.RETURN_ORDER.getType(), order.getIsFirst())) {
                    tags.add(new QueryProduceOrderPageVO.Tag().setTagName("返").setColor("info"));
                }
                tags.add(new QueryProduceOrderPageVO.Tag().setTagName(order.getStockType()).setColor("warning"));
                tags.add(new QueryProduceOrderPageVO.Tag().setTagName(order.getOrderType()).setColor("info"));

                // 添加备注标签
                if (hasOrderNoteLogSet.contains(order.getId())) {
                    tags.add(new QueryProduceOrderPageVO.Tag().setTagName("备").setColor("warning"));
                }

                order.setTags(tags);
            }).collect(Collectors.toList()));
        }

        return resultPage;
    }

    /**
     * 获取订单状态下拉框数据
     *
     * @return
     */
    @Override
    public List<Select> getOrderStatusSelect() {
        return Enum2SelectsUtil.getSelects(OrderEnum.OrderStatus.class, "getDesc", "getStatus");
//
//        List<Select> selects = new ArrayList<>();
//        for (OrderEnum.OrderStatus orderStatus : OrderEnum.OrderStatus.values()) {
//            selects.add(new Select().setLabel(orderStatus.getDesc()).setValue(String.valueOf(orderStatus.getStatus())));
//        }
//        return selects;
    }

    /**
     * 获取订单统计信息
     *
     * @param queryDto
     * @return
     */
    @Override
    public OrderStatInfoVO getOrderStatInfo(QueryProduceOrderPageDTO queryDto) {

        // 获取当前登陆用户拥有的工厂权限
        Set<String> factoryDataPermissions = this.getFactoryDataPermissions();
        if (CollUtil.isEmpty(factoryDataPermissions)) {
            return new OrderStatInfoVO().setTotalQuantity(0L).setTotalOrders(0L).setTotalDesigns(0L);
        }

        // 请求参数预处理
        this.orderPageQueryParamPreHandle(queryDto);

        // 根据条件获取对应订单总数
        Long totalOrders = super.getBaseMapper().countTotalOrders(queryDto, new ArrayList<>(factoryDataPermissions));

        // 根据条件获取总款式
        Long totalDesigns = super.getBaseMapper().countTotalDesigns(queryDto, new ArrayList<>(factoryDataPermissions));

        // 根据条件获取总件数
        Long totalQuantity = super.getBaseMapper().countTotalQuantity(queryDto, new ArrayList<>(factoryDataPermissions));

        return new OrderStatInfoVO().setTotalOrders(totalOrders).setTotalDesigns(totalDesigns)
                .setTotalQuantity(totalQuantity);
    }

    /**
     * 根据订单号获取订单数量统计信息
     *
     * @param orderId
     * @return
     */
    @Override
    public OrderQuantityInfo getOrderQuantityInfo(Long orderId) {
        SysOrder sysOrder = super.getOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getProduceOrderId, orderId));
        Assert.notNull(sysOrder, "订单不存在");

        List<OrderQuantityInfo.Column> columns = new ArrayList<>();
        List<Map<String, Object>> datas = new ArrayList<>();

        // 添加默认列
        columns.add(new OrderQuantityInfo.Column().setTitle("尺码").setKey("type"));

        // 处理下单件数
        if (StrUtil.isNotEmpty(sysOrder.getOrderInfo())) {
            List<NumberInfo> orderInfoNumbers = JSON.parseArray(sysOrder.getOrderInfo(), NumberInfo.class);
            if (CollUtil.isNotEmpty(orderInfoNumbers)) {
                // 提取所有的尺码
                List<String> sizeNames = orderInfoNumbers.stream().map(NumberInfo::getSizeName).collect(Collectors.toList());
                sizeNames.forEach(sizeName -> {
                    columns.add(new OrderQuantityInfo.Column().setKey(sizeName).setTitle(sizeName));
                });

                Map<String, Object> sizeData = new LinkedHashMap<>();
                sizeData.put("type", "下单件数");

                orderInfoNumbers.forEach(numberInfo -> {
                    sizeData.put(numberInfo.getSizeName(), numberInfo.getQuantity());
                });

                // 添加合计列
                columns.add(new OrderQuantityInfo.Column().setTitle("合计").setKey("total"));
                sizeData.put("total", sysOrder.getQuantity());

                datas.add(sizeData);
            }
        }

        // 处理裁床件数
        if (StrUtil.isNotEmpty(sysOrder.getCutBedInfo())) {
            List<NumberInfo> cutInfoNumbers = JSON.parseArray(sysOrder.getCutBedInfo(), NumberInfo.class);
            if (CollUtil.isNotEmpty(cutInfoNumbers)) {
                Map<String, Object> sizeData = new LinkedHashMap<>();
                sizeData.put("type", "裁床件数");

                cutInfoNumbers.forEach(numberInfo -> {
                    sizeData.put(numberInfo.getSizeName(), numberInfo.getQuantityInterval());
                });

                sizeData.put("total", sysOrder.getCutBedQty());
                datas.add(sizeData);
            }
        }
        return new OrderQuantityInfo().setColumns(columns).setData(datas);
    }

    /**
     * 接单
     *
     * @param receiveOrderDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receiveOrders(ReceiveOrderDTO receiveOrderDTO) {

        List<SysOrder> orders = super.list(new LambdaQueryWrapper<SysOrder>()
                .in(SysOrder::getProduceOrderId, receiveOrderDTO.getProducerOrderIds()));

        // 判断里面是否存在非待采购的订单
        boolean allMatch = orders.stream().allMatch(order -> Objects.equals(OrderEnum.OrderStatus.PENDING_ORDERS.getStatus(), order.getStatusInt()));
        Assert.isTrue(allMatch, "存在非待接单的订单");

        // 批量更新订单状态
        orders.forEach(order -> {
            order.setStatus(OrderEnum.OrderStatus.TO_BE_PURCHASED.getDesc());
            order.setStatusInt(OrderEnum.OrderStatus.TO_BE_PURCHASED.getStatus());
        });
        super.updateBatchById(orders);

        // 添加日志
        List<AddOrderLogDTO> addOrderLogs = orders.stream().map(x -> {
            AddOrderLogDTO addOrderLogDTO = new AddOrderLogDTO();
            addOrderLogDTO.setOrderId(x.getId());
            addOrderLogDTO.setTitle("已接单");
            return addOrderLogDTO;
        }).collect(Collectors.toList());
        this.orderLogService.batchAddOrderLog(addOrderLogs);

        // 生成采购单
        this.materialPurchaseService.createPurchaseByOrders(orders);
    }

    /**
     * 打标
     *
     * @param markingOrderDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void markingOrders(MarkingOrderDTO markingOrderDTO) {

        List<Long> orderIds = super.list(new LambdaQueryWrapper<SysOrder>().in(SysOrder::getProduceOrderId, markingOrderDTO.getProduceOrderIds())).stream()
                .map(BaseEntity::getId).distinct().collect(Collectors.toList());
        if (CollUtil.isEmpty(orderIds)) {
            return;
        }

        // 同步订单标签
        for (Long orderId : orderIds) {
            this.orderTagService.synchronizeOrderTags(orderId, markingOrderDTO.getTagIds());
        }

//        // 删除指定标签的原始标签
//        this.orderTagService.remove(new LambdaQueryWrapper<SysOrderTag>().in(SysOrderTag::getOrderId, orderIds));
//
//        // 重新构建订单与标签的关系
//        List<SysOrderTag> sysOrderTags = new ArrayList<>();
//        List<AddOrderLogDTO> addOrderLogs = new ArrayList<>();
//        for (Long orderId : orderIds) {
//            for (Long tagId : markingOrderDTO.getTagIds()) {
//                SysOrderTag orderTag = new SysOrderTag();
//                orderTag.setOrderId(orderId);
//                orderTag.setTagId(tagId);
//                orderTag.setCreateBy(SecurityUtils.getUserId());
//                orderTag.setUpdateBy(SecurityUtils.getUserId());
//                sysOrderTags.add(orderTag);
//            }
//        }
//        this.orderTagService.saveBatch(sysOrderTags);


    }

    /**
     * 计算工价
     *
     * @param calculateWages
     * @return
     */
    @Override
    public String calculateWages(CalculateWagesDTO calculateWages) {
//        // 先尝试从redis中获取，如果获取不到，则调用接口获取
//        String key = String.format("order:calulate:wages:%s", calculateWages.getProduceOrderId());
//        String littleSumConst = this.redisCache.getCacheObject(key);
//
//        if (StrUtil.isNotBlank(littleSumConst)) {
//            BigDecimal result = NumberUtil.mul(littleSumConst, calculateWages.getPriceMultiple());
//            return result.stripTrailingZeros().toPlainString();
//        }
//
//        // 获取该订单对应的 openapi密钥信息
//        SysOrder sysOrder = this.getOrderByProduceOrderId(calculateWages.getProduceOrderId());
//        SysSheinOpenApiSecret openApiSecret = this.sheinOpenApiSecretService.getByFactoryId(sysOrder.getFactoryId());
//        Assert.notNull(openApiSecret, "该工厂未配置密钥信息");
//
//        // 调取接口获取工价
//        QueryProduceOrderInfoByIdReqDTO reqDTO = new QueryProduceOrderInfoByIdReqDTO();
//        reqDTO.setProduceOrderId(calculateWages.getProduceOrderId());
//        QueryProduceOrderInfoByIdResDTO produceOrderInfoByIdResDTO = this.mesApiService.queryProduceOrderInfoById(openApiSecret, reqDTO);
//        ClothCostFeeDetail processingFeeItem = produceOrderInfoByIdResDTO.getClothCostFeeDetail().stream().filter(x -> Objects.equals(x.getCategory(), "加工费"))
//                .findFirst().orElse(null);
//        Assert.notNull(processingFeeItem, "未获取到加工费");
//        Assert.notBlank(Objects.requireNonNull(processingFeeItem).getLittleSumCost(), "未获取到加工费");
//
//        // 添加到缓存中，10分钟过期
//        this.redisCache.setCacheObject(key, processingFeeItem.getLittleSumCost(), 10, TimeUnit.MINUTES);
//
//        BigDecimal result = NumberUtil.mul(processingFeeItem.getLittleSumCost(), calculateWages.getPriceMultiple());
//        return result.stripTrailingZeros().toPlainString();

        return this.orderProcessService.calculateWages(calculateWages);
    }

    /**
     * 复制已有bom的数据查询
     *
     * @param queryDto
     * @return
     */
    @Override
    public List<CopyBomQueryVO> copyBomDataQuery(CopyBomQueryDTO queryDto) {
        // 1. 先获取该款号订单信息
        SysOrder sysOrder = super.getOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getDesignCode, queryDto.getDesignCode()));
        Assert.notNull(sysOrder, "未获取到该款号订单信息");

        // 获取该订单对应的 openapi密钥信息
        SysSheinOpenApiSecret openApiSecret = this.sheinOpenApiSecretService.getByFactoryId(sysOrder.getFactoryId());
        Assert.notNull(openApiSecret, "该工厂未配置密钥信息");

        //2. 调用接口获取订单信息
        QueryProduceOrderInfoByIdReqDTO reqDTO = new QueryProduceOrderInfoByIdReqDTO();
        reqDTO.setProduceOrderId(sysOrder.getProduceOrderId());
        QueryProduceOrderInfoByIdResDTO produceOrderInfoByIdResDTO = this.mesApiService.queryProduceOrderInfoById(openApiSecret, reqDTO);

        // 2. 从订单信息中获取到对应的物料信息
        return Collections.emptyList();
    }

    /**
     * 根据订单号获取订单明细
     *
     * @param produceOrderId
     * @return
     */
    @Override
    public OrderDetailVO getOrderDetail(Long produceOrderId) {
        SysOrder sysOrder = super.getOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getProduceOrderId, produceOrderId));
        Assert.notNull(sysOrder, "订单不存在");

        // 判断订单类型(现在所有订单数据都同步到本地数据库表了，所以不在调用远程接口，都按照本地的逻辑来)
//        return GetOrderDetailFactory.getInstance(sysOrder.getOrderSource()).getOrderDetail(sysOrder);
        return GetOrderDetailFactory.getInstance(OrderEnum.OrderSourceEnum.LOCAL.getOrderSource()).getOrderDetail(sysOrder);
    }

    /**
     * 订单作废
     *
     * @param invalidOrderDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void invalidOrders(InvalidOrderDTO invalidOrderDTO) {
        List<SysOrder> sysOrders = super.listByIds(invalidOrderDTO.getOrderIds());
        Assert.notEmpty(sysOrders, "没有待作废的订单");

        boolean match = sysOrders.stream().allMatch(sysOrder -> Objects.equals(sysOrder.getOrderSource(), OrderEnum.OrderSourceEnum.LOCAL.getOrderSource()));
        Assert.isTrue(match, "存在非本地订单,注意只能作废本地订单");

        sysOrders = sysOrders.stream().peek(sysOrder -> {
            sysOrder.setStatus(OrderEnum.OrderStatus.REPEALED.getDesc());
            sysOrder.setStatusInt(OrderEnum.OrderStatus.REPEALED.getStatus());
        }).collect(Collectors.toList());
        super.updateBatchById(sysOrders);

        // 添加操作日志
        List<AddOrderLogDTO> addOrderLogs = sysOrders.stream().map(x -> {
            AddOrderLogDTO addOrderLogDTO = new AddOrderLogDTO();
            addOrderLogDTO.setOrderId(x.getId());
            addOrderLogDTO.setTitle(OrderEnum.OrderStatus.REPEALED.getDesc());
            return addOrderLogDTO;
        }).collect(Collectors.toList());
        this.orderLogService.batchAddOrderLog(addOrderLogs);
    }

    /**
     * 通知裁床
     *
     * @param produceOrderId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void notifyCuttingBed(Long produceOrderId) {
        SysOrder sysOrder = getOrderByProduceOrderId(produceOrderId);

        // 修改订单状态为裁床中
        sysOrder.setStatus(OrderEnum.OrderStatus.CUTTING_IN_PROGRESS.getDesc());
        sysOrder.setStatusInt(OrderEnum.OrderStatus.CUTTING_IN_PROGRESS.getStatus());
        sysOrder.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(sysOrder);

        // 生成操作日志
        this.orderLogService.addOrderLog(sysOrder.getId(), OrderEnum.OrderStatus.CUTTING_IN_PROGRESS.getDesc());
    }

    /**
     * 基于商品创建订单
     *
     * @param sysGoods
     * @param createOrderDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createOrderByGoods(SysGoods sysGoods, GoodsCreateOrderDTO createOrderDTO) {
        //1. 创建订单
        SysOrder sysOrder = this.doingCreateOrderByGoods(sysGoods, createOrderDTO);

        //2. 创建订单部件
        this.orderPartService.createOrderParts(sysOrder, sysGoods.getId());
    }

    /**
     * 基于订单id获取商品报价单组装数据
     *
     * @param orderId
     * @return
     */
    @Override
    public GoodsQuotationSheetVO getGoodsQuotationSheet(Long orderId) {
        // 查询商品id对应的部件信息
        GoodsQuotationSheetVO goodsQuotationSheetVO = new GoodsQuotationSheetVO();
        goodsQuotationSheetVO.setId(null);

        List<GoodsQuotationSheetPartDTO> quotationSheetParts = this.orderPartService.queryQuotationSheetPartDetail(orderId);
        goodsQuotationSheetVO.setParts(quotationSheetParts);

        Map<Long, String> partIdNameMap = quotationSheetParts.stream().collect(Collectors.toMap(GoodsQuotationSheetPartDTO::getPartId, GoodsQuotationSheetPartDTO::getPartLibrary));

        // 成本统计
        List<GoodsQuotationSheetTotalCastVO> totalCasts = new ArrayList<>();
        List<GoodsQuotationSheetTotalCastVO> partTotalCasts = new ArrayList<>();
        for (GoodsQuotationSheetPartDTO currentPart : quotationSheetParts) {

            // 当前部件的当前颜色的物料总和
            for (GoodsQuotationSheetPartMaterialDTO currentPartColorMaterial : currentPart.getPartMaterials()) {
                // 当前部件的成本统计
                GoodsQuotationSheetTotalCastVO currentPartTotalCast = new GoodsQuotationSheetTotalCastVO();
                currentPartTotalCast.setType(GoodsEnum.GoodsTotalCostTypeEnum.PART.getType());
                currentPartTotalCast.setPartId(currentPart.getPartId());
                currentPartTotalCast.setPartColor(currentPartColorMaterial.getGoodsColor());

                // 当前部件的加工费用
                BigDecimal processingCost;
                if (currentPart.getPartProcess() == null || StrUtil.isBlank(currentPart.getPartProcess().getTotalProcessCosts())) {
                    processingCost = new BigDecimal(0);
                } else {
                    processingCost = new BigDecimal(currentPart.getPartProcess().getTotalProcessCosts());
                }
                processingCost = NumberUtil.round(processingCost, 2);

                // 当前部件的物料金额总和
                BigDecimal materialCost = currentPartColorMaterial.getMaterials().stream()
                        .map(x -> {
                            if (StrUtil.isBlank(x.getAmount())) {
                                return new BigDecimal(0);
                            }
                            return new BigDecimal(x.getAmount());
                        })
                        .reduce(new BigDecimal(0), BigDecimal::add);
                materialCost = NumberUtil.round(materialCost, 2);

                // 总价
                BigDecimal totalPrice = NumberUtil.round(NumberUtil.add(processingCost, materialCost), 2);

                currentPartTotalCast.setTotalPrice(totalPrice.toPlainString());
                currentPartTotalCast.setMaterialCost(materialCost.toPlainString());
                currentPartTotalCast.setProcessingCost(processingCost.toPlainString());
                currentPartTotalCast.setOtherExpenses(null);
                currentPartTotalCast.setPartName(String.format("%s(%s)", currentPart.getPartLibrary(), currentPartColorMaterial.getGoodsColor()));

                partTotalCasts.add(currentPartTotalCast);
                totalCasts.add(currentPartTotalCast);
            }
        }


        // 处理总计
        LinkedHashMap<Long, List<GoodsQuotationSheetTotalCastVO>> partTotalCastMap = partTotalCasts.stream()
                .collect(Collectors.groupingBy(GoodsQuotationSheetTotalCastVO::getPartId, LinkedHashMap::new,
                        Collectors.toList()));

        partTotalCastMap.forEach((partId, partTotalCastList) -> {
            GoodsQuotationSheetTotalCastVO currentPartTotalCast = new GoodsQuotationSheetTotalCastVO();
            currentPartTotalCast.setType(GoodsEnum.GoodsTotalCostTypeEnum.TOTAL_COST.getType());
            currentPartTotalCast.setPartId(partId);
            currentPartTotalCast.setPartColor(null);
            currentPartTotalCast.setPartName(String.format("%s-总价", MapUtil.getStr(partIdNameMap, partId)));

            BigDecimal totalPrice = partTotalCastList.stream().map(x -> new BigDecimal(x.getTotalPrice()))
                    .reduce(new BigDecimal(0), BigDecimal::add);
            totalPrice = NumberUtil.round(totalPrice, 2);
            currentPartTotalCast.setTotalPrice(totalPrice.toPlainString());

            BigDecimal materialCost = partTotalCastList.stream().map(x -> new BigDecimal(x.getMaterialCost()))
                    .reduce(new BigDecimal(0), BigDecimal::add);
            materialCost = NumberUtil.round(materialCost, 2);
            currentPartTotalCast.setMaterialCost(materialCost.toPlainString());

            BigDecimal processingCost = partTotalCastList.stream().map(x -> new BigDecimal(x.getProcessingCost()))
                    .reduce(new BigDecimal(0), BigDecimal::add);
            processingCost = NumberUtil.round(processingCost, 2);
            currentPartTotalCast.setProcessingCost(processingCost.toPlainString());
            currentPartTotalCast.setOtherExpenses(null);
            totalCasts.add(currentPartTotalCast);
        });
        goodsQuotationSheetVO.setTotalCasts(totalCasts);
        return goodsQuotationSheetVO;
    }

    /**
     * 判断订单是否是套装
     *
     * @param produceOrderId
     */
    @Override
    public boolean isSuit(Long produceOrderId) {
        SysOrder sysOrder = this.getOrderByProduceOrderId(produceOrderId);
        return sysOrder.getMultiPiecesQuantity() > 1;
    }

    /**
     * 同步商品报价单部件物料信息到订单中
     *
     * @param sysGoods
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void synchronizedGoodsQuotationSheetPartMaterials(SysGoods sysGoods) {
        // 1. 获取该商品下的对应的所有状态为待采购的订单信息
        List<SysOrder> sysOrders = super.list(new LambdaQueryWrapper<SysOrder>()
                .eq(SysOrder::getSku, sysGoods.getSkc())
                .eq(SysOrder::getStatusInt, OrderEnum.OrderStatus.TO_BE_PURCHASED.getStatus())
        );
        if (CollUtil.isEmpty(sysOrders)) {
            log.debug("该sku:{}下没有待采购的订单信息", sysGoods.getSkc());
            return;
        }

        //2. 获取该sku下的所有商品部件物料信息
        List<SysGoodsPartMaterial> sysGoodsPartMaterials = this.goodsPartMaterialService.list(new LambdaQueryWrapper<SysGoodsPartMaterial>()
                .eq(SysGoodsPartMaterial::getGoodsId, sysGoods.getId())
        );
        List<Long> existsGoodsPartMaterialIds = sysGoodsPartMaterials.stream().map(BaseEntity::getId).collect(Collectors.toList());
        Map<Long, SysGoodsPartMaterial> goodsPartMaterialMap = sysGoodsPartMaterials.stream().collect(Collectors.toMap(BaseEntity::getId, Function.identity(), (a, b) -> b));

        // 3. 逐个更新每个订单中的物料信息
        for (SysOrder currentOrder : sysOrders) {
            // 克隆一份，避免多个订单共用同一个
            List<Long> currentExistsGoodsPartMaterialIds = SerializeUtil.clone(existsGoodsPartMaterialIds);

            Map<Long, SysOrderPart> sourcePartIdOrderPartMap = this.orderPartService.list(new LambdaQueryWrapper<SysOrderPart>()
                    .eq(SysOrderPart::getOrderId, currentOrder.getId())
                    .eq(SysOrderPart::getStatus, CommonStatus.ENABLE.code)
            ).stream().collect(Collectors.toMap(SysOrderPart::getSourceGoodsPartId, Function.identity(), (a, b) -> b));

            // 获取该订单下的部件物料信息
            List<SysOrderPartMaterial> existsOrderPartMaterials = this.orderPartMaterialService.list(new LambdaQueryWrapper<SysOrderPartMaterial>()
                    .eq(SysOrderPartMaterial::getOrderId, currentOrder.getId())
            );
            List<Long> existsOrderPartMaterialIds = existsOrderPartMaterials.stream().map(SysOrderPartMaterial::getSourceGoodsMaterialId).collect(Collectors.toList());
//            Map<Long, SysOrderPartMaterial> orderPartMaterialMap = existsOrderPartMaterials.stream().collect(Collectors.toMap(SysOrderPartMaterial::getSourceGoodsMaterialId, Function.identity(), (a, b) -> b));

            // 获取该订单下的采购单信息
            List<Long> alreadyConfirmGoodsMaterialIds = this.materialPurchaseService.list(new LambdaQueryWrapper<SysMaterialPurchase>()
                            .eq(SysMaterialPurchase::getOrderId, currentOrder.getId())
                            .ne(SysMaterialPurchase::getStatus, MaterialPurchaseEnum.MaterialPurchaseStatusEnum.TO_BE_PURCHASED.getStatus())
                    ).stream().map(SysMaterialPurchase::getSourceGoodsMaterialId)
                    .filter(Objects::nonNull)
                    .distinct().collect(Collectors.toList());
            if (CollUtil.isNotEmpty(alreadyConfirmGoodsMaterialIds)) {
                currentExistsGoodsPartMaterialIds = CollUtil.subtractToList(currentExistsGoodsPartMaterialIds, alreadyConfirmGoodsMaterialIds);
                existsOrderPartMaterialIds = CollUtil.subtractToList(existsOrderPartMaterialIds, alreadyConfirmGoodsMaterialIds);
            }


            // 待删除的商品物料id
            List<Long> needRemoveGoodsPartIds = CollUtil.subtractToList(existsOrderPartMaterialIds, currentExistsGoodsPartMaterialIds);

            // 待新增的商品物料id
            List<Long> needAddGoodsPartIds = CollUtil.subtractToList(currentExistsGoodsPartMaterialIds, existsOrderPartMaterialIds);

            // 待更新的商品物料id
            Set<Long> needUpdateGoodsPartIds = CollUtil.intersectionDistinct(existsOrderPartMaterialIds, currentExistsGoodsPartMaterialIds);


            if (CollUtil.isNotEmpty(needRemoveGoodsPartIds)) {
                List<SysOrderPartMaterial> needRemoveOrderPartMaterials = existsOrderPartMaterials.stream().filter(x -> needRemoveGoodsPartIds.contains(x.getSourceGoodsMaterialId()))
                        .collect(Collectors.toList());
                List<Long> needRemoveOrderPartMaterialIds = needRemoveOrderPartMaterials.stream().map(BaseEntity::getId).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(needRemoveOrderPartMaterialIds)) {
                    this.orderPartMaterialService.removeByIds(needRemoveOrderPartMaterialIds);
                }

                // 删除对应的采购单数据
                this.materialPurchaseService.remove(new LambdaQueryWrapper<SysMaterialPurchase>()
                        .in(SysMaterialPurchase::getSourceGoodsMaterialId, needRemoveGoodsPartIds)
                        .eq(SysMaterialPurchase::getOrderId, currentOrder.getId())
                );
            }

            if (CollUtil.isNotEmpty(needAddGoodsPartIds)) {
                List<SysOrderPartMaterial> needAddOrderPartMaterials = sysGoodsPartMaterials.stream().filter(x -> needAddGoodsPartIds.contains(x.getId())).map(x -> {
                    SysOrderPartMaterial orderPartMaterial = new SysOrderPartMaterial();
                    BeanUtils.copyProperties(x, orderPartMaterial);
                    orderPartMaterial.setOrderId(currentOrder.getId());
                    orderPartMaterial.setOrderPartId(sourcePartIdOrderPartMap.get(x.getGoodsPartId()).getId());
                    orderPartMaterial.setProduceOrderId(Convert.toStr(currentOrder.getProduceOrderId()));
                    orderPartMaterial.setPartCode(null);
                    orderPartMaterial.setGoodsColor(currentOrder.getColor());
                    orderPartMaterial.setSourceGoodsPartId(x.getGoodsPartId());
                    orderPartMaterial.setSourceGoodsMaterialId(x.getId());
                    orderPartMaterial.setCreateBy(SecurityUtils.getUserId());
                    orderPartMaterial.setUpdateBy(SecurityUtils.getUserId());
                    return orderPartMaterial;
                }).collect(Collectors.toList());
                this.orderPartMaterialService.saveBatch(needAddOrderPartMaterials);

                // 添加对应的采购单数据
                List<SysMaterialPurchase> materialPurchases = sysGoodsPartMaterials.stream().filter(x -> needAddGoodsPartIds.contains(x.getId())).map(x -> {
                    SysMaterialPurchase materialPurchase = new SysMaterialPurchase();
                    BeanUtils.copyProperties(x, materialPurchase);
                    materialPurchase.setOrderId(currentOrder.getId());
                    materialPurchase.setProduceOrderId(currentOrder.getProduceOrderId());
                    materialPurchase.setType(2);
                    materialPurchase.setMaterialType(x.getMaterialTypeName());
                    materialPurchase.setPrice(x.getUnitPrice());
                    materialPurchase.setPurchaseCode(null);
                    materialPurchase.setPurchaseType(x.getItem());
                    materialPurchase.setSimpleUse(x.getSinglePieceUsage());
                    materialPurchase.setSingleAmountKg(null);
                    materialPurchase.setSupplierAddr(x.getSupplierAddress());
                    materialPurchase.setSupplierLoss(x.getLoss());
                    materialPurchase.setWeight(x.getGramWeight());
                    materialPurchase.setWidth(x.getBorderedDoorWidth());
                    materialPurchase.setStatus(MaterialPurchaseEnum.MaterialPurchaseStatusEnum.TO_BE_PURCHASED.getStatus());
                    materialPurchase.setFactoryId(currentOrder.getFactoryId());
                    materialPurchase.setCustomerId(currentOrder.getCustomerId());
                    materialPurchase.setPurchasePrice(null);
                    materialPurchase.setPurchaseVolume(null);
                    materialPurchase.setPurchaser(null);
                    materialPurchase.setRecycledMaterialsPrice(null);
                    materialPurchase.setRecycledMaterialsVolume(null);
                    materialPurchase.setSourceGoodsMaterialId(x.getId());
                    materialPurchase.setCreateBy(SecurityUtils.getUserId());
                    materialPurchase.setUpdateBy(SecurityUtils.getUserId());
                    return materialPurchase;
                }).collect(Collectors.toList());
                this.materialPurchaseService.saveBatch(materialPurchases);
            }

            if (CollUtil.isNotEmpty(needUpdateGoodsPartIds)) {
                List<SysOrderPartMaterial> needUpdateOrderPartMaterials = existsOrderPartMaterials.stream().filter(x -> needUpdateGoodsPartIds.contains(x.getSourceGoodsMaterialId()))
                        .peek(x -> {
                            SysGoodsPartMaterial goodsPartMaterial = goodsPartMaterialMap.get(x.getSourceGoodsMaterialId());
                            Long orderPartMaterialId = SerializeUtil.clone(x.getId());
                            BeanUtils.copyProperties(goodsPartMaterial, x);
                            x.setId(orderPartMaterialId);
                            x.setUpdateBy(SecurityUtils.getUserId());
                        }).collect(Collectors.toList());
                this.orderPartMaterialService.updateBatchById(needUpdateOrderPartMaterials);

                // 更新对应的采购单信息
                List<SysMaterialPurchase> needUpdateMaterialPurchases = this.materialPurchaseService.list(new LambdaQueryWrapper<SysMaterialPurchase>()
                                .eq(SysMaterialPurchase::getOrderId, currentOrder.getId())
                                .eq(SysMaterialPurchase::getStatus, MaterialPurchaseEnum.MaterialPurchaseStatusEnum.TO_BE_PURCHASED.getStatus())
                                .isNotNull(SysMaterialPurchase::getSourceGoodsMaterialId)
                        ).stream().filter(x -> needUpdateGoodsPartIds.contains(x.getSourceGoodsMaterialId()))
                        .peek(x -> {
                            SysGoodsPartMaterial goodsPartMaterial = goodsPartMaterialMap.get(x.getSourceGoodsMaterialId());
                            Long materialPurchaseId = SerializeUtil.clone(x.getId());
                            BeanUtils.copyProperties(goodsPartMaterial, x);
                            x.setId(materialPurchaseId);
                            x.setMaterialType(goodsPartMaterial.getMaterialTypeName());
                            x.setPrice(goodsPartMaterial.getUnitPrice());
                            x.setPurchaseCode(null);
                            x.setPurchaseType(goodsPartMaterial.getItem());
                            x.setSimpleUse(goodsPartMaterial.getSinglePieceUsage());
                            x.setSingleAmountKg(null);
                            x.setSupplierAddr(goodsPartMaterial.getSupplierAddress());
                            x.setSupplierLoss(goodsPartMaterial.getLoss());
                            x.setWeight(goodsPartMaterial.getGramWeight());
                            x.setWidth(goodsPartMaterial.getBorderedDoorWidth());
                            x.setSourceGoodsMaterialId(goodsPartMaterial.getId());
                            x.setUpdateBy(SecurityUtils.getUserId());
                        }).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(needUpdateMaterialPurchases)) {
                    this.materialPurchaseService.updateBatchById(needUpdateMaterialPurchases);
                }

            }
        }

    }

    /**
     * 更新订单状态为车缝中
     *
     * @param produceOrderId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderStatusToInTheCarSeam(Long produceOrderId) {
        SysOrder sysOrder = this.getOrderByProduceOrderId(produceOrderId);
        Assert.isTrue(Objects.equals(sysOrder.getStatusInt(), OrderEnum.OrderStatus.CUTTING_IN_PROGRESS.getStatus()), "该订单不是裁床中状态，无法更新为车缝中");

        sysOrder.setStatus(OrderEnum.OrderStatus.IN_THE_CAR_SEAM.getDesc());
        sysOrder.setStatusInt(OrderEnum.OrderStatus.IN_THE_CAR_SEAM.getStatus());
        sysOrder.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(sysOrder);

        // 添加操作日志
        this.orderLogService.addOrderLog(sysOrder.getId(), OrderEnum.OrderStatus.IN_THE_CAR_SEAM.getDesc());
    }

    /**
     * 根据订单号获取对应的订单id集合
     *
     * @param produceOrderIds
     * @return
     */
    @Override
    public List<Long> getOrderIdsByProduceOrderIds(List<Long> produceOrderIds) {
        if (CollUtil.isEmpty(produceOrderIds)) {
            return new ArrayList<>();
        }
        return super.list(new LambdaQueryWrapper<SysOrder>()
                .in(SysOrder::getProduceOrderId, produceOrderIds)
        ).stream().map(BaseEntity::getId).collect(Collectors.toList());
    }

    /**
     * 修改订单状态外为尾部中
     *
     * @param orderId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderStatusToInTheTail(Long orderId) {
        SysOrder sysOrder = super.getById(orderId);
        Assert.notNull(sysOrder, "该订单不存在");
        Assert.isTrue(Objects.equals(sysOrder.getStatusInt(), OrderEnum.OrderStatus.IN_THE_CAR_SEAM.getStatus()), "该订单不是车缝中状态，无法更新为尾部中");

        sysOrder.setStatus(OrderEnum.OrderStatus.IN_THE_TAIL.getDesc());
        sysOrder.setStatusInt(OrderEnum.OrderStatus.IN_THE_TAIL.getStatus());
        sysOrder.setUpdateBy(SecurityUtils.getUserId());
        super.updateById(sysOrder);

        // 添加操作日志
        this.orderLogService.addOrderLog(sysOrder.getId(), OrderEnum.OrderStatus.IN_THE_TAIL.getDesc());
    }

    /**
     * 打印skc贴纸
     *
     * @param printSkcStickerDTO
     * @return
     */
    @Override
    public String printSkcSticker(PrintSkcStickerDTO printSkcStickerDTO) {
        // 根据订单号查询订单信息
        SysOrder sysOrder = super.getOne(new LambdaQueryWrapper<SysOrder>()
                .eq(SysOrder::getProduceOrderId, printSkcStickerDTO.getProduceOrderId())
                .ne(SysOrder::getStatusInt, OrderEnum.OrderStatus.REPEALED.getStatus())
        );
        Assert.notNull(sysOrder, "该订单不存在");

        // 提取对应的尺码信息
        OrderQuantityInfo sizeInfo = printSkcStickerDTO.getSizeInfo();
        Map<String, Object> printSizeInfoData = Optional.ofNullable(sizeInfo.getData()).orElse(new ArrayList<>()).stream().filter(x -> x.containsKey("type"))
                .filter(x -> Objects.equals(x.get("type"), "打印件数")).findFirst().orElse(null);
        if (printSizeInfoData == null) {
            throw new BusinessException("没有找到关于打印件数相关数据");
        }

        // 构建数据,生成二维码对象
        List<SkcStickerQrCodeDTO> skcStickerQrCodeDTOS = new ArrayList<>();
        for (OrderQuantityInfo.Column currentSizeColumn : sizeInfo.getColumns()) {

            if (Objects.equals(currentSizeColumn.getTitle(), "尺码") || Objects.equals(currentSizeColumn.getTitle(), "合计")) {
                continue;
            }

            // 获取该尺寸的打印数量
            Integer currentSizeNum = MapUtil.getInt(printSizeInfoData, currentSizeColumn.getKey(), null);
            if (currentSizeNum == null || currentSizeNum <= 0) {
                continue;
            }

            // 根据尺码数量，生成对应数量的二维码信息
            for (int num = 0; num < currentSizeNum; num++) {
                SkcStickerQrCodeDTO skcStickerQrCodeDTO = new SkcStickerQrCodeDTO();
                skcStickerQrCodeDTO.setProduceOrderId(String.valueOf(sysOrder.getProduceOrderId()));
                skcStickerQrCodeDTO.setSkc(sysOrder.getSku());
                skcStickerQrCodeDTO.setSizeName(currentSizeColumn.getTitle());
                skcStickerQrCodeDTOS.add(skcStickerQrCodeDTO);
            }

        }

        // 生成pdf
        return PrintSkcStickerPdfFactory.getInstance(printSkcStickerDTO.getPrintType()).pdfAndUploadToMinio(skcStickerQrCodeDTOS);
        //return GeneratorPrintSkcStickerPdfUtil.generatorQrCodePdfAndUploadToMinio(skcStickerQrCodeDTOS);
    }

    /**
     * 根据订单号获取打印skc贴纸 尺码数量信息
     *
     * @param produceOrderId
     * @return
     */
    @Override
    public OrderQuantityInfo getPrintSkcStickerOrderQuantityInfo(Long produceOrderId) {
        SysOrder sysOrder = this.getOrderByProduceOrderId(produceOrderId);

        List<OrderQuantityInfo.Column> columns = new ArrayList<>();
        List<Map<String, Object>> datas = new ArrayList<>();

        // 添加默认列
        columns.add(new OrderQuantityInfo.Column().setTitle("尺码").setKey("type"));

        // 处理下单件数
        if (StrUtil.isNotEmpty(sysOrder.getOrderInfo())) {
            List<NumberInfo> orderInfoNumbers = JSON.parseArray(sysOrder.getOrderInfo(), NumberInfo.class);
            if (CollUtil.isNotEmpty(orderInfoNumbers)) {
                // 提取所有的尺码
                List<String> sizeNames = orderInfoNumbers.stream().map(NumberInfo::getSizeName).collect(Collectors.toList());
                sizeNames.forEach(sizeName -> {
                    columns.add(new OrderQuantityInfo.Column().setKey(sizeName).setTitle(sizeName));
                });

                Map<String, Object> sizeData = new LinkedHashMap<>();
                sizeData.put("type", "下单件数");

                orderInfoNumbers.forEach(numberInfo -> {
                    sizeData.put(numberInfo.getSizeName(), numberInfo.getQuantity());
                });

                // 添加合计列
                columns.add(new OrderQuantityInfo.Column().setTitle("合计").setKey("total"));
                sizeData.put("total", sysOrder.getQuantity());

                datas.add(sizeData);

                // 处理打印贴纸数量
                Map<String, Object> printSkcStickerSizeData = SerializeUtil.clone(sizeData);
                printSkcStickerSizeData.put("type", "打印件数");
                datas.add(printSkcStickerSizeData);
            }
        }
        return new OrderQuantityInfo().setColumns(columns).setData(datas);
    }

    /**
     * 获取状态侧边栏信息
     *
     * @param queryDto
     * @return
     */
    @Override
    public List<StatusInfo> getStatusInfo(QueryProduceOrderPageDTO queryDto) {
        // 获取当前登陆用户拥有的工厂权限
        Set<String> factoryDataPermissions = this.getFactoryDataPermissions();

        List<StatusInfo> statusTotals;
        if (CollUtil.isEmpty(factoryDataPermissions)) {
            statusTotals = new ArrayList<>();
        } else {
            // 去除状态过滤
            queryDto.setBatchStatus(null);
            // 预处理数据
            this.orderPageQueryParamPreHandle(queryDto);
            // 执行查询
            statusTotals = super.getBaseMapper().getStatusTotals(queryDto, new ArrayList<>(factoryDataPermissions));
        }
        return this.extractStatusInfos(statusTotals);
    }

    /**
     * 国内大货下单
     *
     * @param produceOrderId
     */
    @Override
    public void domesticBulkGoodsPlaceOrder(Long produceOrderId) {
        // 获取订单详情
        OrderDetailVO orderDetail = this.getOrderDetail(produceOrderId);
        SysOrder sysOrder = super.getById(orderDetail.getId());
        SysGoods sysGoods = this.goodsService.getGoodsBySku(sysOrder.getSku());

        //1. 先调用款式同步接口
        this.goodsService.synchronizedStyle(sysGoods.getId());

        // 2. 构建请求接口参数
        doingDomesticBulkGoodsPlaceOrder(orderDetail, sysOrder, sysGoods);
    }


    /**
     * 验证生成计划单的参数
     *
     * @param generatePlanDTO
     * @return
     */
    @Override
    public String validateGeneratePlan(GeneratePlanDTO generatePlanDTO) {
        List<SysOrder> sysOrders = super.list(new LambdaQueryWrapper<SysOrder>()
                .in(SysOrder::getProduceOrderId, generatePlanDTO.getProduceOrderIds())
        );
        return sysOrders.stream().filter(x -> StrUtil.isNotBlank(x.getPlanOrderNumber()))
                .map(x -> Convert.toStr(x.getProduceOrderId()))
                .collect(Collectors.joining(","));
    }

    /**
     * 生成计划单
     *
     * @param generatePlanDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generatePlan(GeneratePlanDTO generatePlanDTO) {
        // 1. 排除存在已有计划单号的订单
        List<SysOrder> sysOrders = super.list(new LambdaQueryWrapper<SysOrder>()
                .in(SysOrder::getProduceOrderId, generatePlanDTO.getProduceOrderIds())
        );
        sysOrders = sysOrders.stream().filter(x -> StrUtil.isBlank(x.getPlanOrderNumber())).collect(Collectors.toList());
        if (CollUtil.isEmpty(sysOrders)) {
            throw new BusinessException("没有待生成计划单号的订单");
        }

        // 生成计划单号
        String planOrderNumber = String.format("PL%s", IdWorker.getIdStr());
        sysOrders = sysOrders.stream().peek(x -> {
            x.setPlanOrderNumber(planOrderNumber);
            x.setUpdateBy(SecurityUtils.getUserId());
        }).collect(Collectors.toList());
        super.updateBatchById(sysOrders);

        // 生成操作日志
        List<AddOrderLogDTO> addOrderLogList = sysOrders.stream().map(x -> new AddOrderLogDTO(x.getId(), "生成计划单号")).collect(Collectors.toList());
        this.orderLogService.batchAddOrderLog(addOrderLogList);
    }

    /**
     * 执行国内下单接口
     *
     * @param orderDetail
     * @param sysOrder
     * @param sysGoods
     */
    private void doingDomesticBulkGoodsPlaceOrder(OrderDetailVO orderDetail,
                                                  SysOrder sysOrder, SysGoods sysGoods) {

        SysCustomer sysCustomer = this.customerService.getById(sysOrder.getCustomerId());
        long totalQuantity = 0L;

        DomesticBulkGoodsPlaceOrderDTO domesticBulkGoodsPlaceOrderDTO = new DomesticBulkGoodsPlaceOrderDTO();
        domesticBulkGoodsPlaceOrderDTO.setDueDate(orderDetail.getDeliveryTime());
        domesticBulkGoodsPlaceOrderDTO.setMeasurer(null);
        domesticBulkGoodsPlaceOrderDTO.setOrderPno(orderDetail.getProduceOrderId());
        domesticBulkGoodsPlaceOrderDTO.setPpFrom("ERP");
        domesticBulkGoodsPlaceOrderDTO.setThirdUid(orderDetail.getProduceOrderId());
        domesticBulkGoodsPlaceOrderDTO.setCustomerId(Convert.toStr(sysOrder.getCustomerId()));
        if (sysCustomer != null) {
            domesticBulkGoodsPlaceOrderDTO.setCustomerName(sysCustomer.getCustomerName());
        }
        domesticBulkGoodsPlaceOrderDTO.setMrchds(null);
        domesticBulkGoodsPlaceOrderDTO.setOrderDate(orderDetail.getPlaceOrderTime());
        domesticBulkGoodsPlaceOrderDTO.setOrderNo(null);
        domesticBulkGoodsPlaceOrderDTO.setRemark(null);
        domesticBulkGoodsPlaceOrderDTO.setWkspcd(null);
        // 订单明细构建
        List<DomesticBulkGoodsPlaceOrderDTO.Line> lineList = new ArrayList<>();
        DomesticBulkGoodsPlaceOrderDTO.Line line = new DomesticBulkGoodsPlaceOrderDTO.Line();
        if (StrUtil.isNotBlank(sysOrder.getOrderInfo())) {
            List<NumberInfo> numberInfos = JsonUtil.parseArray(sysOrder.getOrderInfo(), NumberInfo.class);
            if (CollUtil.isNotEmpty(numberInfos)) {
                line.setItemList(numberInfos.stream().map(x -> {
                    DomesticBulkGoodsPlaceOrderDTO.Item item = new DomesticBulkGoodsPlaceOrderDTO.Item();
                    item.setItemQty(Convert.toLong(x.getQuantity()));
                    item.setSizeNo(x.getSizeName());
                    item.setRemark(null);
                    item.setSuitno(null);
                    return item;
                }).collect(Collectors.toList()));

                // 总件数
                totalQuantity = line.getItemList().stream().mapToLong(DomesticBulkGoodsPlaceOrderDTO.Item::getItemQty).sum();
            }
        }

        // 主物料信息配置
        if (CollUtil.isNotEmpty(orderDetail.getParts())) {
            List<GoodsMaterialItemDTO> materialItems = orderDetail.getParts().stream()
                    .flatMap(x -> x.getPartMaterials().get(0).getMaterials().stream())
                    .collect(Collectors.toList());

            // 主料
            GoodsMaterialItemDTO mainMaterial;
            // 找出主料中用量最多的那个物料作为主料
            List<GoodsMaterialItemDTO> mainMaterialItems = materialItems.stream().filter(x -> x.getItem().startsWith("面料")).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(mainMaterialItems)) {
                mainMaterial = mainMaterialItems.stream()
                        .max(Comparator.comparing(GoodsMaterialItemDTO::getSinglePieceUsage))
                        .get();
            } else {
                // 没有主料，则使用用量最大的一个物料作为主料
                mainMaterial = materialItems.stream()
                        .max(Comparator.comparing(GoodsMaterialItemDTO::getSinglePieceUsage))
                        .get();
            }

//            GoodsQuotationSheetPartDTO mainPart = orderDetail.getParts().get(0);
//            GoodsMaterialItemDTO mainMaterial = mainPart.getPartMaterials().get(0).getMaterials().get(0);
            line.setMainMcolor(mainMaterial.getColor());
            line.setMainMid(mainMaterial.getSku());
            line.setMainMname(mainMaterial.getMaterialName());
            line.setMainSpec(null);
        }

        line.setProdId(sysGoods.getGoodsType());
        line.setProdName(sysGoods.getGoodsType());
        line.setStylId(sysGoods.getSkc());
        line.setStylName(sysGoods.getSkc());

        // 构建物料清单,工艺清单
        if (CollUtil.isNotEmpty(orderDetail.getParts())) {
            List<DomesticBulkGoodsPlaceOrderDTO.Bom> bomList = new ArrayList<>();
            List<DomesticBulkGoodsPlaceOrderDTO.Tec> tecList = new ArrayList<>();
            for (GoodsQuotationSheetPartDTO part : orderDetail.getParts()) {

                // 物料
                for (GoodsQuotationSheetPartMaterialDTO partMaterial : part.getPartMaterials()) {
                    for (GoodsMaterialItemDTO material : partMaterial.getMaterials()) {
                        DomesticBulkGoodsPlaceOrderDTO.Bom bom = new DomesticBulkGoodsPlaceOrderDTO.Bom();
                        bom.setMainMterial(material.getItem().startsWith("面料"));
                        bom.setMaterialId(material.getSku());
                        bom.setCadpartcd(null);
                        bom.setCutWidth(null);
                        bom.setCutWstrat(null);
                        bom.setMaspec(null);
                        bom.setMaterialBatchno(null);
                        bom.setMaterialClrnm(material.getColor());
                        bom.setMaterialColor(material.getColor());
                        bom.setMaterialCom(material.getIngredients());
                        bom.setMaterialName(material.getMaterialName());
                        bom.setMaterialTypeId(null);
                        bom.setMaterialTypeName(material.getTypeName());
                        bom.setMaterialUsage(null);
                        bom.setMtrlsz(null);
                        bom.setRefrnc(null);
                        bom.setRemark(material.getRemark());
                        bom.setS_materialId(null);
                        bom.setThirdUid(material.getSku());
                        // 总用量 = 单件用量 * 订单件数
                        bom.setTolConsu(Convert.toDouble(material.getSinglePieceUsage()) * totalQuantity);
                        bom.setUniConsu(Convert.toDouble(material.getSinglePieceUsage()));
                        bom.setUnitcd(material.getUnit());
                        bom.setUnitnm(material.getUnit());
                        bom.setWidth(Convert.toDouble(material.getBorderedDoorWidth()));
                        bomList.add(bom);
                    }
                }

                // 二次工艺
                for (GoodsQuotationSheetPartSecondProcessDTO partSecondProcess : part.getPartSecondProcesses()) {
                    DomesticBulkGoodsPlaceOrderDTO.Tec tec = new DomesticBulkGoodsPlaceOrderDTO.Tec();
                    tec.setCraftdetail(partSecondProcess.getProcessName());
                    tec.setPdptcd(Convert.toStr(part.getPartId()));
                    tec.setPdptnm(part.getPartLibrary());
                    tecList.add(tec);
                }
            }
            line.setBomList(bomList);
            line.setTecList(tecList);
        }

        line.setPattern_no(null);
        line.setPattern_sty(null);
        line.setPrtrnm(sysOrder.getColor());
        line.setRemark(null);
        line.setSkuName(orderDetail.getSku());
        line.setSkuNo(orderDetail.getSku());
        line.setSkuSpec(orderDetail.getSku());
        line.setSkuType(orderDetail.getSku());
        line.setUnitnm(null);
        line.setWorker(null);

        lineList.add(line);
        domesticBulkGoodsPlaceOrderDTO.setLineList(lineList);

        this.synchronizedMesService.domesticBulkGoodsPlaceOrder(domesticBulkGoodsPlaceOrderDTO);
    }

    /**
     * 提取状态信息
     *
     * @param statusTotals
     * @return
     */
    private List<StatusInfo> extractStatusInfos(List<StatusInfo> statusTotals) {
        Map<String, Integer> existsStatusQuantityMap = Optional.ofNullable(statusTotals).orElse(new ArrayList<>()).stream().collect(Collectors.toMap(StatusInfo::getStatus, StatusInfo::getQuantity));

        // 编辑所有状态
        List<StatusInfo> statusInfos = new ArrayList<>();
        for (OrderEnum.OrderStatus statusEnum : OrderEnum.OrderStatus.values()) {
            StatusInfo statusInfo = new StatusInfo();
            String status = Convert.toStr(statusEnum.getStatus());
            statusInfo.setStatus(status);
            statusInfo.setStatusName(statusEnum.getDesc());
            statusInfo.setQuantity(existsStatusQuantityMap.getOrDefault(status, 0));
            statusInfos.add(statusInfo);
        }
        return statusInfos;
    }

    /**
     * 获取当前登录用户拥有的工厂权限id集合
     *
     * @return
     */
    private Set<String> getFactoryDataPermissions() {
        // 获取当前登陆用户拥有的工厂权限
        Set<String> factoryDataPermissions;
        if (SecurityUtils.getLoginUser().getUser().isAdmin()) {
            factoryDataPermissions = this.sysFactoryService.list(new LambdaQueryWrapper<SysFactory>().eq(SysFactory::getStatus, CommonStatus.ENABLE.code)).stream()
                    .map(x -> StrUtil.toString(x.getId())).collect(Collectors.toSet());
        } else {
            factoryDataPermissions = SecurityUtils.getLoginUser().getFactoryDataPermissions();
        }
        return factoryDataPermissions;
    }

    /**
     * 订单查询请求参数预处理
     *
     * @param queryDto
     */
    private void orderPageQueryParamPreHandle(QueryProduceOrderPageDTO queryDto) {
        // 预处理数据
        queryDto.setBatchProduceOrderIds(Optional.ofNullable(queryDto.getBatchProduceOrderIds()).orElse(new ArrayList<>())
                .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList()));
        queryDto.setBatchSkus(Optional.ofNullable(queryDto.getBatchSkus()).orElse(new ArrayList<>())
                .stream().filter(StrUtil::isNotBlank).collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(queryDto.getBatchProduceOrderIds())) {
            queryDto.setProduceOrderId(null);
        }
        if (CollUtil.isNotEmpty(queryDto.getBatchSkus())) {
            queryDto.setSku(null);
        }
    }

    /**
     * 执行基于商品创建订单
     *
     * @param sysGoods
     * @param createOrderDTO
     * @return
     */
    private SysOrder doingCreateOrderByGoods(SysGoods sysGoods, GoodsCreateOrderDTO createOrderDTO) {
        OrderEnum.OrderStockType orderStockTypeEnum = OrderEnum.OrderStockType.getInstanceByType(createOrderDTO.getStockType());
        Assert.notNull(orderStockTypeEnum, "备货类型错误");

        // 生成订单信息
        SysOrder sysOrder = new SysOrder();
        sysOrder.setId(null);
        sysOrder.setAcceptOrderTime(createOrderDTO.getAcceptOrderTime());
        sysOrder.setCutBedInfo(null);
        sysOrder.setCutBedQty(null);
        sysOrder.setCutInfoStr(null);
        sysOrder.setDeliveryTime(createOrderDTO.getDeliveryTime());
        sysOrder.setDesignCode(sysGoods.getDesignCode());
        sysOrder.setFactoryId(SecurityUtils.getFactoryId());
        sysOrder.setFactoryPermission(JsonUtil.toJsonString(Lists.newArrayList(SecurityUtils.getFactoryId())));
        sysOrder.setIsFirst(Convert.toInt(this.isFirst(sysGoods.getSkc())));
        sysOrder.setIsUrgent(createOrderDTO.getIsUrgent());

        // order相关字段处理
        this.setOrderInfo(createOrderDTO, sysOrder);

        sysOrder.setPic(sysGoods.getPic());
        sysOrder.setPlaceOrderTime(new Date());

        // 先生成一个唯一的id，订单创建后，在覆盖掉
        sysOrder.setProduceOrderId(IdUtil.getSnowflakeNextId());

        sysOrder.setProducer(this.sysFactoryService.getFactoryName(SecurityUtils.getFactoryId()));
        sysOrder.setRefSku(null);
        sysOrder.setSecondProcess(this.extractSecondProcessJsonStr(sysGoods));
        sysOrder.setSku(sysGoods.getSkc());

        // 设置本地订单初始状态为待接单
        sysOrder.setStatus(OrderEnum.OrderStatus.PENDING_ORDERS.getDesc());
        sysOrder.setStatusInt(OrderEnum.OrderStatus.PENDING_ORDERS.getStatus());

        sysOrder.setStockType(orderStockTypeEnum.getDesc());
        sysOrder.setStockTypeInt(orderStockTypeEnum.getType());
        sysOrder.setCustomerId(createOrderDTO.getCustomerId());
        sysOrder.setOrderSource(OrderEnum.OrderSourceEnum.LOCAL.getOrderSource());
        sysOrder.setColor(createOrderDTO.getColor());
        sysOrder.setMultiPiecesQuantity(this.goodsPartService.getMultiPiecesQuantity(sysGoods.getId()));
        sysOrder.setCreateBy(SecurityUtils.getUserId());
        sysOrder.setUpdateBy(SecurityUtils.getUserId());
        super.save(sysOrder);

        // 更新生产单号
        sysOrder.setProduceOrderId(this.generatorProduceOrderId(SecurityUtils.getFactoryId(), sysOrder.getId()));
        super.updateById(sysOrder);

        return sysOrder;
    }

    /**
     * 判断是否是首单
     *
     * @param sku
     * @return
     */
    private boolean isFirst(String sku) {
        int count = super.count(new LambdaQueryWrapper<SysOrder>()
                .eq(SysOrder::getSku, sku)
        );
        return count == 0;
    }


    /**
     * 生成生产单号
     *
     * @param factoryId
     * @param sysOrderId
     * @return
     */
    private Long generatorProduceOrderId(Long factoryId, Long sysOrderId) {
        // 生成生产单号，规则： 当前年份+工厂id+订单id，例如 25+01+00001
        // 获取当前年份的后两位
        String year = DateUtil.thisYear() % 100 + "";

        // 格式化工厂ID为2位，不足前面补0
        String factoryCode = StrUtil.padPre(factoryId + "", 2, '0');

        // 格式化订单ID为5位，不足前面补0
        String orderCode = StrUtil.padPre(sysOrderId + "", 5, '0');

        return Convert.toLong(year + factoryCode + orderCode);
    }

    /**
     * 设置新建订单中 关于Order相关属性赋值处理
     *
     * @param createOrderDTO
     * @param sysOrder
     */
    private void setOrderInfo(GoodsCreateOrderDTO createOrderDTO, SysOrder sysOrder) {
        OrderEnum.OrderType orderTypeEnum = OrderEnum.OrderType.getInstanceByType(createOrderDTO.getOrderType());
        Assert.notNull(orderTypeEnum, "订单类型错误");

        List<GoodsCreateOrderSizeDTO> sizes = createOrderDTO.getSizes();
        int quantity = sizes.stream().mapToInt(GoodsCreateOrderSizeDTO::getQuantity).sum();
        sysOrder.setOrderInfo(JsonUtil.toJsonString(sizes));
        sysOrder.setOrderInfoStr(null);
        sysOrder.setOrderPrice(BigDecimal.valueOf(createOrderDTO.getOrderPrice()));
        sysOrder.setOrderRecordId(null);
        sysOrder.setOrderType(orderTypeEnum.getDesc());
        sysOrder.setOrderTypeInt(orderTypeEnum.getType());
        sysOrder.setQuantity(quantity);
    }


    /**
     * 提取商品中的面辅料二次工艺数据
     *
     * @param sysGoods
     * @return
     */
    private String extractSecondProcessJsonStr(SysGoods sysGoods) {
        // 查询该商品对应的二次工艺
        List<SysGoodsSecondProcess> goodsSecondProcesses = this.goodsSecondProcessService.queryGoodsSecondProcesses(sysGoods.getId());
        List<SecondProcessInfo> secondProcessInfoList = goodsSecondProcesses.stream().map(x -> {
            SecondProcessInfo secondProcessInfo = new SecondProcessInfo();
            BeanUtils.copyProperties(x, secondProcessInfo);
            secondProcessInfo.setUnitPrice(new BigDecimal(x.getUnitPrice()));
            return secondProcessInfo;
        }).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(secondProcessInfoList)) {
            return JsonUtil.toJsonString(secondProcessInfoList);
        }
        return null;
    }


    /**
     * 获取订单号对应的订单信息
     *
     * @param produceOrderId
     * @return
     */
    private SysOrder getOrderByProduceOrderId(Long produceOrderId) {
        SysOrder sysOrder = super.getOne(new LambdaQueryWrapper<SysOrder>().eq(SysOrder::getProduceOrderId, produceOrderId));
        Assert.notNull(sysOrder, "订单不存在");
        return sysOrder;
    }
}
